#include "Matrix4.h"

namespace OCPP
{
	namespace Cesium
	{
		Matrix4 Matrix4::computePerspectiveFieldOfView(
			double fovY,
			double aspectRatio,
			double near,
			double far
		) {
			double bottom = tan(fovY * 0.5);
			double _column1Row1 = 1.0 / bottom;
			double _column0Row0 = _column1Row1 / aspectRatio;
			double _column2Row2 = (far + near) / (near - far);
			double _column3Row2 = (2.0 * far * near) / (near - far);
			Matrix4 result;
			result[0] = _column0Row0;
			result[1] = 0.0;
			result[2] = 0.0;
			result[3] = 0.0;
			result[4] = 0.0;
			result[5] = _column1Row1;
			result[6] = 0.0;
			result[7] = 0.0;
			result[8] = 0.0;
			result[9] = 0.0;
			result[10] = _column2Row2;
			result[11] = -1.0;
			result[12] = 0.0;
			result[13] = 0.0;
			result[14] = _column3Row2;
			result[15] = 0.0;
			return result;
		};

		Matrix4 Matrix4::computeOrthographicOffCenter(
			double left,
			double right,
			double bottom,
			double top,
			double near,
			double far
		) {
			double a = 1.0 / (right - left);
			double b = 1.0 / (top - bottom);
			double c = 1.0 / (far - near);

			double tx = -(right + left) * a;
			double ty = -(top + bottom) * b;
			double tz = -(far + near) * c;
			a *= 2.0;
			b *= 2.0;
			c *= -2.0;
			Matrix4 result;
			result[0] = a;
			result[1] = 0.0;
			result[2] = 0.0;
			result[3] = 0.0;
			result[4] = 0.0;
			result[5] = b;
			result[6] = 0.0;
			result[7] = 0.0;
			result[8] = 0.0;
			result[9] = 0.0;
			result[10] = c;
			result[11] = 0.0;
			result[12] = tx;
			result[13] = ty;
			result[14] = tz;
			result[15] = 1.0;
			return result;
		};

		Matrix4 Matrix4::computePerspectiveOffCenter(
			double left,
			double right,
			double bottom,
			double top,
			double near,
			double far
		) {
			double column0Row0 = (2.0 * near) / (right - left);
			double column1Row1 = (2.0 * near) / (top - bottom);
			double column2Row0 = (right + left) / (right - left);
			double column2Row1 = (top + bottom) / (top - bottom);
			double column2Row2 = -(far + near) / (far - near);
			double column2Row3 = -1.0;
			double column3Row2 = (-2.0 * far * near) / (far - near);
			Matrix4 result;
			result[0] = column0Row0;
			result[1] = 0.0;
			result[2] = 0.0;
			result[3] = 0.0;
			result[4] = 0.0;
			result[5] = column1Row1;
			result[6] = 0.0;
			result[7] = 0.0;
			result[8] = column2Row0;
			result[9] = column2Row1;
			result[10] = column2Row2;
			result[11] = column2Row3;
			result[12] = 0.0;
			result[13] = 0.0;
			result[14] = column3Row2;
			result[15] = 0.0;
			return result;
		};

		Matrix4 Matrix4::computeInfinitePerspectiveOffCenter(
			double left,
			double right,
			double bottom,
			double top,
			double near
		) {
			double column0Row0 = (2.0 * near) / (right - left);
			double column1Row1 = (2.0 * near) / (top - bottom);
			double column2Row0 = (right + left) / (right - left);
			double column2Row1 = (top + bottom) / (top - bottom);
			double column2Row2 = -1.0;
			double column2Row3 = -1.0;
			double column3Row2 = -2.0 * near;
			Matrix4 result;
			result[0] = column0Row0;
			result[1] = 0.0;
			result[2] = 0.0;
			result[3] = 0.0;
			result[4] = 0.0;
			result[5] = column1Row1;
			result[6] = 0.0;
			result[7] = 0.0;
			result[8] = column2Row0;
			result[9] = column2Row1;
			result[10] = column2Row2;
			result[11] = column2Row3;
			result[12] = 0.0;
			result[13] = 0.0;
			result[14] = column3Row2;
			result[15] = 0.0;
			return result;
		};
	}
}

